package com.xmhmyh.generalframework.project.sys.service.impl;

import com.alibaba.druid.util.DaemonThreadFactory;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xmhmyh.generalframework.common.BaseServiceImpl;
import com.xmhmyh.generalframework.common.constants.Constants;
import com.xmhmyh.generalframework.common.conversion.Bean2SelectConverter;
import com.xmhmyh.generalframework.common.enums.ResponseCode;
import com.xmhmyh.generalframework.common.enums.YesOrNo;
import com.xmhmyh.generalframework.common.utils.MyBeanUtils;
import com.xmhmyh.generalframework.common.vo.SelectVO;
import com.xmhmyh.generalframework.framework.exceptions.ManageExceptions;
import com.xmhmyh.generalframework.framework.exceptions.WxExceptions;
import com.xmhmyh.generalframework.project.sys.conversion.Dictionary2DictionaryDTOConversion;
import com.xmhmyh.generalframework.project.sys.dto.DictionaryDTO;
import com.xmhmyh.generalframework.project.sys.entity.Account;
import com.xmhmyh.generalframework.project.sys.entity.Dictionary;
import com.xmhmyh.generalframework.project.sys.entity.Params;
import com.xmhmyh.generalframework.project.sys.entity.User;
import com.xmhmyh.generalframework.project.sys.enums.*;
import com.xmhmyh.generalframework.project.sys.mapper.DictionaryMapper;
import com.xmhmyh.generalframework.project.sys.service.IAccountService;
import com.xmhmyh.generalframework.project.sys.service.IDictionaryService;
import org.apache.tomcat.util.bcel.Const;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: 于丁
 * @DateTime: 2020/7/24 9:09 上午
 */
@Service
public class DictionaryServiceImpl extends BaseServiceImpl<DictionaryMapper, Dictionary> implements IDictionaryService {

    @Autowired
    private IAccountService accountService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveHandler(User user, DictionaryDTO dictionaryDTO) {
        Dictionary dictionary = new Dictionary();
        if (checkCodeRepeat(dictionaryDTO.getCode(), dictionaryDTO.getId(), user.getAccountId())) {
            throw new ManageExceptions(ResponseCode.CODE_REPEAT);
        }
        BeanUtils.copyProperties(dictionaryDTO, dictionary);
        boolean isAdd = true;
        if (dictionaryDTO.getId() == null) {
            MyBeanUtils.setSysInfo(dictionary, user.getId(), user.getAccountId());
            dictionary.setId(uidGenerator.getUID());
            dictionary.setLvl(DictionaryLvl.LV1.getValue());
            save(dictionary);
        } else {
            isAdd = false;
            Dictionary old = getById(dictionaryDTO.getId());
            if (old == null) {
                throw new ManageExceptions(ResponseCode.ENTITY_NOT_FIND);
            }
            MyBeanUtils.updateSysInfo(dictionary, user.getId());
            dictionary.setId(old.getId());
            dictionary.setCreateBy(old.getCreateBy());
            dictionary.setEnabled(old.getEnabled());
            dictionary.setCreateTime(old.getCreateTime());
            updateById(dictionary);
        }
        // 删除所有子集
        deleteByParentsId(dictionary.getId());
        // 保存子集
        List<DictionaryDTO> childDTOList = dictionaryDTO.getChildList();
        List<Dictionary> childList = new ArrayList<>();
        for (DictionaryDTO item : childDTOList) {
            item.setId(uidGenerator.getUID());
            item.setParentsId(dictionary.getId());
            Dictionary saveDictionary = new Dictionary();
            BeanUtils.copyProperties(item, saveDictionary);
            saveDictionary.setEnabled(YesOrNo.YES.getValue());
            save(saveDictionary);
            childList.add(saveDictionary);
        }
        if (user.getAccountId() == Constants.SUPER_ACCOUNT_ID) {
            // 复制到子账户
            dictionary.setChildList(childList);
            if (isAdd) {
                syncCreateDictionary(dictionary);
            } else {
                syncEditDictionary(dictionary);
            }
        }

    }

    /**
     * @Author: 于丁
     * @Description:
     * @DateTime: 批量修改 4:44 下午
     * @Params: * @param: null
     * @Return {@link null}
     */
    public void syncEditDictionary(Dictionary dictionary) {
        // 账户级别的不需要同步
        if (dictionary.getType() == ParamsType.ACCOUNT.getValue()) {
            return;
        }
        removeByCode(dictionary.getCode(), dictionary.getId());
        syncCreateDictionary(dictionary);
    }

    @Override
    public void removeByCode(String code, Long notRemoveId) {
        LambdaQueryWrapper<Dictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dictionary::getCode, code);
        if (notRemoveId != null) {
            queryWrapper.ne(Dictionary::getId, notRemoveId);
        }
        List<Dictionary> dictionaryList = list(queryWrapper);
        for (Dictionary dictionary : dictionaryList) {
            deleteByParentsId(dictionary.getId());
            removeById(dictionary.getId());
        }
    }

    /**
     * @Author: 于丁
     * @Description: 同步创建系统用户字典
     * @DateTime: 2020/10/10 4:13 下午
     * @Params: * @param: null
     * @Return {@link null}
     */
    public void syncCreateDictionary(Dictionary dictionary) {
        // 需要同步的账户
        List<Account> accountList = new ArrayList<>();
        // 判断params类型
        accountList = accountService.list();
        List<Dictionary> dictionaryList = new ArrayList<>();
        for (Account account : accountList) {
            // 排除掉超级管理账户
            if (account.getId().equals(Constants.SUPER_ACCOUNT_ID)) {
                continue;
            }
            Dictionary d = new Dictionary();
            BeanUtils.copyProperties(dictionary, d);
            MyBeanUtils.setSysInfo(d, account.getAdminUserId(), account.getId());
            d.setId(uidGenerator.getUID());
            dictionaryList.add(d);
            List<Dictionary> childList = dictionary.getChildList();
            for (Dictionary child : childList) {
                Dictionary childCopy = new Dictionary();
                BeanUtils.copyProperties(child, childCopy);
                childCopy.setParentsId(d.getId());
                childCopy.setId(uidGenerator.getUID());
                MyBeanUtils.setSysInfo(childCopy, account.getAdminUserId(), account.getId());
                dictionaryList.add(childCopy);
            }
        }
        saveBatch(dictionaryList);
    }

    @Override
    public DictionaryDTO loadMore(Long id) {
        Dictionary dictionary = getById(id);
        if (dictionary == null) {
            throw new ManageExceptions(ResponseCode.ENTITY_NOT_FIND);
        }
        DictionaryDTO dictionaryDTO = Dictionary2DictionaryDTOConversion.conversion(dictionary);
        dictionaryDTO.setChildList(getChildListByParentsId(dictionaryDTO.getId()));
        return dictionaryDTO;
    }

    /**
     * @Author: 于丁
     * @Description: 根据父级删除
     * @DateTime: 2020/8/11 3:54 下午
     * @Params: * @param: parentsId 父ID
     * @Return
     */
    private void deleteByParentsId(Long parentsId) {
        LambdaQueryWrapper<Dictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dictionary::getParentsId, parentsId);
        remove(queryWrapper);
    }


    /**
     * @Author: 于丁
     * @Description: 检查code是否重复
     * @DateTime: 2020/8/11 4:15 下午
     * @Params: * @param: null
     * @Return {@link null}
     */
    private Boolean checkCodeRepeat(String code, Long id, Long accountId) {
        LambdaQueryWrapper<Dictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dictionary::getCode, code);
        queryWrapper.eq(Dictionary::getAccountId, accountId);
        if (id != null) {
            queryWrapper.ne(Dictionary::getId, id);
        }
        return count(queryWrapper) > 0 ? true : false;
    }


    @Override
    public List<DictionaryDTO> getChildListByParentsId(Long parentsId) {
        LambdaQueryWrapper<Dictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dictionary::getParentsId, parentsId);
        List<Dictionary> dictionaries = list(queryWrapper);
        return Dictionary2DictionaryDTOConversion.conversion(dictionaries);
    }

    @Override
    public List<Dictionary> getChildList(Long parentsId) {
        LambdaQueryWrapper<Dictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dictionary::getParentsId, parentsId);
        List<Dictionary> dictionaries = list(queryWrapper);
        return dictionaries;
    }

    @Override
    public Dictionary getByCode(String code, Long accountId) {
        LambdaQueryWrapper<Dictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dictionary::getCode, code);
        queryWrapper.eq(Dictionary::getAccountId, accountId);
        Dictionary dictionary = getOne(queryWrapper);
        return dictionary;
    }


    @Override
    public List<SelectVO> getSelectVoByCode(String code, Long accountId) {
        // 获取用户字典数据
        Dictionary dictionary = getByCode(code, accountId);
        if (dictionary == null) {
            throw new WxExceptions(ResponseCode.DICTIONARY_NOT_FIND);
        }
        List<DictionaryDTO> dictionaryDTOList = getChildListByParentsId(dictionary.getId());
        // 转换成selectVO
        List<SelectVO> selectVOList = Bean2SelectConverter.converter(dictionaryDTOList, DictionaryDTO::getValue, DictionaryDTO::getCode);
        return selectVOList;
    }

}
